﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using LevenBlog.Core.Data;
using LevenBlog.Core.Entities;
using LevenBlog.Core.Service;
using LevenBlog.Core.Mvc;
using LevenBlog.Core.Cache;
using LevenBlog.Core.User;
using LevenBlog.Core.Utils;

namespace LevenBlog.Core.Mvc
{
    public abstract class BlogBaseController : BaseController
    {
        private static Dictionary<string, DateTime> onlineCache = new Dictionary<string, DateTime>();
        private static DateTime onlineClearTime = DateTime.Now;
        private static List<string> blackips = null;
        private static object lockObject = new object();
        private static ReaderWriterLockSlim requestLock = new ReaderWriterLockSlim();
        
        private static BlogViewEngine currentViewEngine;

        protected List<string> blackIps
        {
            get
            {
                if (blackips == null)
                {
                    string[] badIps = Config.Get(Provider).badip.Split('|');
                    lock (lockObject)
                    {
                        if (blackips == null)
                        {
                            blackips = new List<string>();
                            foreach (string bi in badIps)
                            {
                                blackips.Add(bi.Trim());
                            }
                        }
                    }
                }
                return blackips;
            }
        }

        public BlogBaseController()
        {
            //viewLocator = new BlogViewLocator(Config.Get(Provider).skinpath);
            //WebFormViewEngine viewEngine = (WebFormViewEngine)ViewEngine;
            //viewEngine.ViewLocator = viewLocator;
            if (currentViewEngine == null)
            {
                string skinpath = Config.Get(Provider).skinpath;
                lock (lockObject)
                {
                    if (currentViewEngine == null)
                    {
                        currentViewEngine = new BlogViewEngine(skinpath);
                        ViewEngines.Engines.Add(currentViewEngine);
                    }
                }
            }
            ViewData["skinname"] = currentViewEngine.SkinName;
            ViewData["skinpath"] = string.Format("skins/{0}/", Config.Get(Provider).skinpath);
            ViewData["state"] = State.Get(Provider);
            ViewData["config"] = Config.Get(Provider);
            ViewData["categories"] = Category.Get(Provider);
        }

        protected string SkinName
        {
            get { return currentViewEngine.SkinName; }
            set
            {
                ViewData["skinname"] = value;
                ViewData["skinpath"] = string.Format("skins/{0}/", value);
                currentViewEngine.SkinName=value;
            }
        }

        protected override void OnResultExecuting(ResultExecutingContext filterContext)
        {
        }

        [NonAction]
        public ActionResult Message(MessageEntity messageEntity)
        {
            ViewData.Model = messageEntity;
            this.title = string.Format("{0} - {1}", messageEntity.Title, Config.Get(Provider).title);
            return View("message");
        }

        [NonAction]
        public ActionResult Message(string title, string content, MessageIcon icon)
        {
            MessageEntity message = new MessageEntity();
            message.Title = title;
            message.Content = content;
            message.JumpUrl = "<a href=\"javascript:history.back();\" title=\"返回\">返回</a>";
            message.Icon = icon;
            return Message(message);
        }

        [NonAction]
        public ActionResult Message(string title, string content, RouteValueDictionary jumproute, string jumpName, MessageIcon icon)
        {
            MessageEntity message = new MessageEntity();
            message.Title = title;
            message.Content = content;
            message.JumpRoute = jumproute;
            message.JumpUrl = jumpName;
            message.Icon = icon;
            return Message(message);
        }

        [NonAction]
        public ActionResult Message(string title, string content, object jumproute, string jumpname, MessageIcon icon)
        {
            return Message(title, content, new RouteValueDictionary(jumproute), jumpname, icon);
        }

        [NonAction]
        public ActionResult ResponseFile(int id)
        {
            FileResult fileResult = new FileResult(Provider);
            fileResult.FileID = id;
            return fileResult;
        }

        [NonAction]
        protected override void OnException(ExceptionContext filterContext)
        {
            lb_log log = new lb_log();
            log.user = Membership.User.name;
            log.time = DateTime.Now;
            //UrlHelper url = new UrlHelper(new ViewContext(filterContext, "error", "", (filterContext.Controller as Controller).ViewData, (filterContext.Controller as Controller).TempData));
            //UrlHelper url = new UrlHelper(new ViewContext(filterContext, "error", filterContext.Controller.ViewData, filterContext.Controller.TempData));
            UrlHelper url = (filterContext.Controller as Controller).Url;
            log.page = url.RouteUrl(filterContext.RouteData.Values);
            log.ip = Fetch.UserIp;
            StringBuilder sb = new StringBuilder();
            Exception e = filterContext.Exception;
            int num = 1;
            while (e != null)
            {
                sb.AppendFormat("{0}.{1}\r\n", num, e.Message);
                e = e.InnerException;
            }
            log.message = sb.ToString();
            Log.Write(Provider, log);
            filterContext.ExceptionHandled = true;
            filterContext.Result = Message("系统错误", "对不起,系统出现了未处理的错误.", MessageIcon.Error);
            //filterContext.ExceptionHandled = true;
            base.OnException(filterContext);
        }

        [NonAction]
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!Config.Get(Provider).isopen)
            {
                //filterContext.Cancel = true;
                MessageEntity message = new MessageEntity();
                message.Title = "站点已经被关闭";
                message.Content = "本站目前已经关闭,如果疑问,请与管理员联系.";
                message.JumpUrl = "<a href=\"javascript:history.back();\" title=\"返回\">返回</a>";
                message.Icon = MessageIcon.Error;
                (filterContext.Controller as Controller).ViewData.Model = message;
                ViewResult view = new ViewResult();
                view.ViewData = (filterContext.Controller as Controller).ViewData;
                view.ViewName = "message";
                //view.ViewEngine = (filterContext.Controller as Controller).ViewEngine;
                filterContext.Result = view;
            }
            bool StateChange = false; // 是否修改了State
            lb_state state = State.Get(Provider);
            lb_config config = Config.Get(Provider);
            //开始计算访问量
            HttpCookie cookie = filterContext.HttpContext.Request.Cookies[WebConfig.PrefixKey + "VisitInfomation"];
            DateTime lastVisit = DateTime.Now.AddYears(-1);
            if (cookie != null)
            {
                DateTime.TryParse(cookie.Value, out lastVisit);
            }
            else
            {
                cookie = new HttpCookie(WebConfig.PrefixKey + "VisitInfomation");
            }
            if (((TimeSpan)(DateTime.Now - lastVisit)).TotalMinutes > 15)
            {
                state.hits++;
                StateChange = true;
            }
            cookie.Value = DateTime.Now.ToString();
            filterContext.HttpContext.Response.Cookies.Add(cookie);
            //开始检查是否有权post
            if (config.posttime > 0)
            {
                if (Request.Form.Count > 0)
                {
                    if (((TimeSpan)(DateTime.Now - lastVisit)).TotalSeconds < config.posttime)
                    {
                        //filterContext.Cancel = true;
                        MessageEntity message = new MessageEntity();
                        message.Title = "无法提交数据";
                        message.Content = string.Format("对不起,您连续提交数据的速度过快,请在{0}秒后重试.", config.posttime);
                        message.JumpUrl = "<a href=\"javascript:history.back();\" title=\"返回\">返回</a>";
                        message.Icon = MessageIcon.Error;
                        (filterContext.Controller as Controller).ViewData.Model = message;
                        ViewResult view = new ViewResult();
                        view.ViewData = (filterContext.Controller as Controller).ViewData;
                        view.ViewName = "message";
                        //view.ViewEngine = (filterContext.Controller as Controller).ViewEngine;
                        filterContext.Result = view;
                    }
                }
            }
            //检查是否为允许IP
            if (!string.IsNullOrEmpty(config.badip))
            {
                var find = blackIps.FirstOrDefault(b => b == Fetch.UserIp);
                if (!String.IsNullOrEmpty(find))
                {
                    //filterContext.Cancel = true;
                    MessageEntity message = new MessageEntity();
                    message.Title = "权限错误";
                    message.Content = "对不起,您无权访问本站,如有疑问,请与管理员联系.";
                    message.JumpUrl = "<a href=\"javascript:history.back();\" title=\"返回\">返回</a>";
                    message.Icon = MessageIcon.Error;
                    (filterContext.Controller as Controller).ViewData.Model = message;
                    ViewResult view = new ViewResult();
                    view.ViewData = (filterContext.Controller as Controller).ViewData;
                    view.ViewName = "message";
                    //view.ViewEngine = (filterContext.Controller as Controller).ViewEngine;
                    filterContext.Result = view;
                }
            }
            //开始计算在线
            string ip = Fetch.UserIp;
            DateTime lastActive = DateTime.Now;
            if (!String.IsNullOrEmpty(ip)) {
                //lock (lockObject) {
                //    if (onlineCache.ContainsKey(ip)) {
                //        onlineCache.Remove(ip);
                //    }
                //    onlineCache.Add(ip, lastActive);
                //}
                //ThreadPool.QueueUserWorkItem(new WaitCallback(e => {
                    requestLock.EnterWriteLock();
                    onlineCache[ip] = lastActive;
                    requestLock.ExitWriteLock();
                //}));
            }
            if (((TimeSpan)(lastActive - onlineClearTime)).TotalMinutes > 30) //每30分钟清理一次在线
            {
                requestLock.EnterReadLock();
                var outTimeUsers = onlineCache.Where(o => ((TimeSpan)(lastActive - o.Value)).TotalMinutes > 30).ToList();
                requestLock.ExitReadLock();
                requestLock.EnterWriteLock();
                for (int i = 0; i < outTimeUsers.Count; i++) {
                    onlineCache.Remove(outTimeUsers[i].Key);
                }
                requestLock.ExitWriteLock();
                //lock (lockObject) {
                //    var outTimeUsers = onlineCache.Where(o => ((TimeSpan)(lastActive - o.Value)).TotalMinutes > 30).ToList();
                //    //foreach (var outUser in outTimeUsers)
                //    //{
                //    //    onlineCache.Remove(outUser.Key);
                //    //}
                //    for (int i = 0; i < outTimeUsers.Count; i++) {
                //        onlineCache.Remove(outTimeUsers[i].Key);
                //    }
                //}
                onlineClearTime = lastActive;
            }
            ViewData["online"] = onlineCache.Count;
            if (onlineCache.Count > state.online)
            {
                state.online = onlineCache.Count;
                StateChange = true;
            }
            //修改State
            if (StateChange)
            {
                State.Update(Provider, state);
            }
            base.OnActionExecuting(filterContext);
        }

        [NonAction]
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            ViewData["querynum"] = Provider.QueryNum;
        }
    }
}
